#include <all_wlib.h>
#pragma hdrstop

#include "int.h"

//---------------------------------------------------------------------------
int RTL_CALLBACK idSortSite( Sort_t left, Sort_t right )  { return StrCmpI( SORTI(left)->Site.Text(),SORTI(right)->Site.Text() ); }
int RTL_CALLBACK idSortAddr( Sort_t left, Sort_t right )  { return StrCmpI( SORTI(left)->Host.Text(),SORTI(right)->Host.Text() ); }
int RTL_CALLBACK idSortSize( Sort_t left, Sort_t right )  { return SORTI(left)->Size - SORTI(right)->Size; }
int RTL_CALLBACK idSortDate( Sort_t left, Sort_t right )  { return SORTI(left)->CmpTime( *SORTI(right), false ); }
int RTL_CALLBACK idSortSiteI( Sort_t left, Sort_t right ) { return -idSortSite(left,right); }
int RTL_CALLBACK idSortAddrI( Sort_t left, Sort_t right ) { return -idSortAddr(left,right); }
int RTL_CALLBACK idSortSizeI( Sort_t left, Sort_t right ) { return -idSortSize(left,right); }
int RTL_CALLBACK idSortDateI( Sort_t left, Sort_t right ) { return -idSortDate(left,right); }

int RTL_CALLBACK idSortLoad( Sort_t left, Sort_t right )
  {  int rc;

     rc = StrCmpI( SORTI(left)->Host.Text(),SORTI(right)->Host.Text() );
     if ( rc ) return rc;

     rc = StrCmpI( SORTI(left)->Site.Text(),SORTI(right)->Site.Text() );
     if ( rc ) return rc;

     rc = StrCmpI( SORTI(left)->Url.Text(),SORTI(right)->Url.Text() );
     if ( rc ) return rc;

 return 0;
}

void GetPart( CTParser& in,char end,char *str,int sz )
  {  char ch;
    sz--;
    while( (ch=in.GetChar()) != 0 && ch != '\n' && ch != '\r' ) {
      if ( ch == end ) {
        *str++ = 0;
        return;
      }
      if ( sz ) {
        *str++ = ch;
        sz--;
      }
    }
    THROW( "The end of part not found in string" )
}
int FindPart( char **text,char *part[],int cn )
  {
    for ( int n = 0,len; n < cn; n++ )
      if ( StrNCmpI(*text,part[n],len = strlen(part[n])) == 0 ) {
        *text += len;
        return n;
      }
 return -1;
}
//---------------------------------------------------------------------------
void UrlInfo::Set( tpGroups tp,CONSTSTR str )
  {  char txt[ 1000 ];
     char *m;

     TStrCpy( txt, str );
     if ( (m=strchr(txt,'\t')) != NULL ) *m = 0;

     switch( tp ) {
       case GRP_SITE: Site = txt; break;
       case GRP_ADDR: Host = txt; break;
       case GRP_DATE: Time.Set(txt); break;
     }
}

int UrlInfo::CmpTime( const UrlInfo& p, bool Filter ) const
  {  int res;
     res = ((int)Time.year) - ((int)p.Time.year);
     if (res != 0) return res;

     res = ((int)Time.mon) - ((int)p.Time.mon);
     if (res != 0) return res;

     res = ((int)Time.mday) - ((int)p.Time.mday);
     if (res != 0) return res;

     if ( Filter )
       return 0;

     res = ((int)Time.hour) - ((int)p.Time.hour);
     if (res != 0) return res;

     res = ((int)Time.min) - ((int)p.Time.min);
     if (res != 0) return res;

     res = ((int)Time.sec) - ((int)p.Time.sec);
     if (res != 0) return res;

 return 0;
}

bool UrlInfo::SetCTime( char *str )
  {  static char *Months[12] = { "Jan ","Feb ","Mar ","Apr ","May ","Jun ",
                                 "Jul ","Aug ","Sep ","Oct ","Nov ","Dec " };
     static char *Days[7]    = { "Sun ","Mon ","Tue ","Wed ","Thu ","Fri ","Sat " };
     int n;

    if ( strlen(str) != 24 )
      return false;

    n = FindPart( &str,Days,sizeof(Days)/sizeof(Days[0]) );
    if (n == -1 ) return false;

    n = FindPart( &str,Months,sizeof(Months)/sizeof(Months[0]) );
    if (n == -1 ) return false;
    Time.mon = (WORD)n+1;

    int Time_mday,Time_hour, Time_min, Time_sec,Time_year;
    if ( sscanf( str,"%02d %02d:%02d:%02d %4d",
                 &Time_mday,
                 &Time_hour, &Time_min, &Time_sec,
                 &Time_year ) != 5 )
     return false;

    Time.mday = (WORD)Time_mday;
    Time.hour = (WORD)Time_hour;
    Time.min  = (WORD)Time_min;
    Time.sec  = (WORD)Time_sec;
    Time.year = (WORD)Time_year;

 return true;
}

CONSTSTR UrlInfo::TypeStr( tpGroups tp )
  {
    switch( tp ) {
      case GRP_SITE: return Site.Text();
      case GRP_ADDR: return Host.Text();
      case GRP_DATE: return Time.GetStr(NULL,0,"%d-%m-%Y");
    }
 return NULL;
}

bool UrlInfo::Load( CTParser& in,AnsiString& error )
  {  char  buff[ 1000 ],ch;
     char *m;
     int   num;
     DEFTRYVAR( ex )


     TRY(1)
       error = "";

       if ( in.NextGet() != '\"' )
         return false;

       //URL
       in.GetExact( "\"" );
       GetPart( in,'\"',buff,sizeof(buff) );

       num = 0;
       if ( strncmp(buff,"ftp",3) == 0  && (buff[3] == ':' || buff[3] == '/') ) num = 3;
       if ( strncmp(buff,"http",4) == 0 && (buff[3] == ':' || buff[3] == '/') ) num = 4;
       if ( num )
         while( buff[num] && strchr(":/\\0123456789",buff[num]) != NULL ) num++;

       if (buff[num] == 0) return false;

       m = strchr( buff+num,'/' );
       if ( m ) {
         *m = 0;
         Site = buff+num;
         Url  = m+1;
       } else {
         Site = buff+num;
         Url  = "";
       }
       num = Site.Chr(':');
       if (num != -1) Site.SetChar( num,0 );
       in.GetExact( "," );

       if ( Site[0] == 0 || Url[0] == 0 ||
            (Site[0] == '*' && Site[1] == 0) )
         return false;

       //HOST
       GetPart( in,',',buff,sizeof(buff) );
       Host = buff;

       if ( Host.Cmp("0.0.0.0") )
         return false;

       //SIZE
       GetPart( in,',',buff,sizeof(buff) );
       Size = atoi(buff);
       if ( !Size )
         return false;

       //DATE
       in.GetExact( "\"" );
       GetPart( in,'\"',buff,sizeof(buff) );
       if ( !SetCTime(buff) )
         THROW( Message("The string [%s] is not valid time string",buff) )

     CATCH(ex,1)
       error = AnsiString("Error: \"") + Ex2Str(ex) + "\"\n"
               "In file line: " + in.GetY() + "\n"
               "In file pos: " + in.GetX() + "\n";
       return false;
     CATCH_END(1)
 return true;
}
//---------------------------------------------------------------------------
void NameArray::Load( void )
  {  PHConfigItem p = Opt->Key->ConfigGetCreate( "Aliases" ),
                  it;
     NameInfo     nm;
     int          cn = p->Read("Count",0);

    for ( int n = 0; n < cn; n++ ) {
      it = p->ConfigGetCreate( Message("Item%d",n) );
      nm.Addr = it->Read( "Address","" );
      nm.Name = it->Read( "Name","" );

      if ( !nm.Addr.Length() || !nm.Name.Length() ) continue;
      Add( nm );
    }
    SortAddr();
}

void NameArray::Save( void )
  {  PHConfigItem p = Opt->Key->ConfigGetCreate( "Aliases" ),
                  it;
     PNameInfo    nm;

    p->Write( "Count", Count() );
    for ( int n = 0; n < Count(); n++ ) {
      it = p->ConfigGetCreate( Message("Item%d",n) );
      nm = Item(n);
      it->Write( "Address", nm->Addr.Text() );
      it->Write( "Name",    nm->Name.Text() );
    }
}

CONSTSTR NameArray::DeName( CONSTSTR str )
  {  static char buff[ 500 ];
     int       cn,n,pos;
     CONSTSTR  m;
     PNameInfo p;
     NameInfo  key;

     if ( !GOPT( "UseNames",FALSE ) )
       return str;

     cn      = StrColCount(str,",");
     buff[0] = 0;

     for ( pos = 0,n = 1; n <= cn; n++ ) {
       if ( strLen(buff) >= sizeof(buff) ) break;

       m = StrGetCol(str,n,",");
       while( *m && isspace(*m) ) m++;

       key.Addr = m;
       if ( (p=Item(FindAddr(key))) != NULL )
         m = p->Name.Text();

       if (buff[0]) StrCat( buff, ", ", sizeof(buff) );
       StrCat( buff+pos, m, sizeof(buff) );
     }
 return buff;
}

static int RTL_CALLBACK idAddrSort( const NameInfo *left,const NameInfo *right )
  {
 return strcmpi( left->Addr.c_str(), right->Addr.c_str() );
}

void NameArray::SortAddr( void )
  {
     Sort( idAddrSort );
}

int NameArray::FindAddr( const NameInfo& ni )
  {
 return Search( ni, idAddrSort, NULL ); 
}

